<?php
class Macys_Base_Config {

	public static $m_pInstance;
	CONST APIPROXY = 'mashery';
	CONST APISERVICES = 'services';
	CONST KEY = 'key';
	CONST MCOMSITE = 'mcom';
	CONST BCOMSITE = 'bcom';
	CONST SESSION_NAME = 'MACYS_CONFIG';


	CONST CLIENT_HEADER = 'client-id';
	CONST CUSTOMER_HEADER = 'customer-id';

	private $log;
	private $config;
	private $mode;
	private $valid_modes = array (self::APIPROXY, self::APISERVICES);
	private $site;
	private $valid_sites = array(self::MCOMSITE, self::BCOMSITE);
	/**
	 * constructor for log
	 */
	private $session;
	private $proxyServerChecked = false;

	private function __construct(){
		$this->log = Zend_Registry::get('log');
		$this->session = new Macys_Base_Session();
		if(!Zend_Session::namespaceIsset(self::SESSION_NAME)) {
			$rconfig = Zend_Registry::get('MACYS_CONFIG');
			$this->sessionData('CONFIG', $rconfig);
			$this->config = $this->sessionData('CONFIG');
		}
		else {
			$this->config = $this->sessionData('CONFIG');
		}
	}


	/**
	 * Singleton instance of the User
	 * as User data is not shared one instance per user
	 */
	public static function getInstance() {
		if (!self::$m_pInstance){
			self::$m_pInstance = new self();
		}
		return self::$m_pInstance;
	}

	public function save() {
		return $this->sessionData('CONFIG', $this->config);
	}

	/**
	 * User gets the Services Gateway url
	 * Used by OAuth Server & Direct Api Call
	 * Will have restricted access
	 */
	public function getServicesUri() {
		return $this->config[$this->getSite()][self::APISERVICES]['url'];
	}

	/**
	 * Provides the user with Client Facing Url for Services
	 * This will be Mashery Url mostly
	 */
	public function getApiUri() {
		return $this->config[$this->getSite()][self::APIPROXY]['url'];
	}

	public function getUri() {
		if($this->config['mode'] == self::APIPROXY)
		return $this->getApiUri();
		else
		return $this->getServicesUri();
	}

	/**
	 * This Function used in Abstract Class for Services
	 * Provides the Class with all the required Conf info to Services
	 * @param string $serviceName
	 */
	public function getServiceConfig($serviceName) {
		$conf = array();
		$conf['api_uri'] = $this->getUri();
		$clientHeader = $this->getApiKey($serviceName);
		if(!is_null($clientHeader)) {
			$conf[Macys_Constants::MACYS_CLIENT_HEADER] = $clientHeader;
			if($this->getMode() == self::APISERVICES) {
				$custHeader = $this->getApiKey($serviceName . 'cust');
				if(!is_null($custHeader))
				$conf[Macys_Constants::MACYS_CUSTOMER_HEADER] = $custHeader;
			}
		}
		return $conf;
	}


	public function getApiKey($serviceName) {
		if(isset($this->config[$this->getSite()][$this->getMode()][self::KEY][$serviceName]))
		return $this->config[$this->getSite()][$this->getMode()][self::KEY][$serviceName];
		return null;
	}

	public function setApiKey($serviceName, $keyValue) {
		if(isset($this->config[$this->getSite()][$this->getMode()][self::KEY][$serviceName])) {
			$this->config[$this->getSite()][$this->getMode()][self::KEY][$serviceName] = $keyValue;
			$this->save();
		}
		else {
			throw new Macys_Base_Exception('Cannot set Key for Undefined ServiceNames : ' . $serviceName);
		}
	}


	public function getMode() {
		return $this->config['mode'];
	}

	public function setMode($mode) {
		if(in_array($mode, $this->valid_modes)) {
			//$this->mode = $mode;
			$this->config['mode'] = $mode;
			$this->save();
		}
		else {
			throw new Macys_Base_Exception('Invalid Mode Please set Valid Mode');
		}
	}

	public function getValues($key) {
		if(isset($this->config[$key]))
		return $this->config[$key];
		return null;
	}

	/**
	 * Used for Showing on UI and Back saving it in users session
	 *
	 * */
	public function getAllKeysForDisplay() {
		$keys = array();
		foreach ($this->valid_sites as $site) {
			foreach ($this->valid_modes as $mode) {
				foreach ($this->config[$site][$mode][self::KEY] as $a=>$value) {
					$key = $site . "_" . $mode . "_" . $a;
					$keys[$key] = $value;
				}
			}
		}
		return $keys;
	}

	public function setAllKeysFromInput($params) {
		if(!is_array($params)) {
			throw new Macys_Base_Exception('Input is not an array ');
		}
		foreach ($params as $key => $value) {
			$keys = explode("_", $key);
			if(count($keys) == 3)
			$this->setSiteModeServiceNameValParams($keys[0], $keys[1], $keys[2], $value);
		}
	}

	public function getOAuthAndUrlsForDisplay() {
		$urls = array();
		$urls['bcom_mashery_url'] = $this->config[self::BCOMSITE][self::APIPROXY]['url'];
		$urls['bcom_services_url'] = $this->config[self::BCOMSITE][self::APISERVICES]['url'];
		$urls['bcom_oauth_url'] = $this->config[self::BCOMSITE]['oauth']['url'];
		$urls['bcom_mashery_oauth_clientid'] = $this->config[self::BCOMSITE][self::APIPROXY]['oauth']['client_id'];
		$urls['bcom_mashery_oauth_secret'] = $this->config[self::BCOMSITE][self::APIPROXY]['oauth']['secret'];
		$urls['mcom_mashery_url'] = $this->config[self::MCOMSITE][self::APIPROXY]['url'];
		$urls['mcom_services_url'] = $this->config[self::MCOMSITE][self::APISERVICES]['url'];
		$urls['mcom_oauth_url'] = $this->config[self::MCOMSITE]['oauth']['url'];
		$urls['mcom_mashery_oauth_clientid'] = $this->config[self::MCOMSITE][self::APIPROXY]['oauth']['client_id'];
		$urls['mcom_mashery_oauth_secret'] = $this->config[self::MCOMSITE][self::APIPROXY]['oauth']['secret'];
		$urls['mode'] = $this->getMode();
		$urls['site'] = $this->getSite();
		return $urls;
	}

	public function setOAuthAndUrlsFromDisplay($params) {
		$u = $this->getOAuthAndUrlsForDisplay();
		foreach ($u as $key => $value) {
			if(isset($params[$key])) {
				$x = explode('_', $key);
				if(count($x) > 3) {
					if($x[3] == 'clientid')
					$this->config[$x[0]][$x[1]][$x[2]]['client_id'] = $params[$key];
					else
					$this->config[$x[0]][$x[1]][$x[2]][$x[3]] = $params[$key];
				}
				else {
					if(count($x) > 2)
					$this->config[$x[0]][$x[1]][$x[2]] = $params[$key];
					if(count($x) == 1) {
						$this->config[$key] = $params[$key];
					}
				}
			}
		}
		$this->save();
	}

	private function setSiteModeServiceNameValParams($site, $mode, $serviceName, $serval, $keyFlag = False) {
		if(!in_array($site, $this->valid_sites)) {
			throw new Macys_Base_Exception('Invalid SITE Please set Valid Site');
		}
		if(!in_array($mode, $this->valid_modes)) {
			throw new Macys_Base_Exception('Invalid Mode Please set Valid Mode');
		}
		if($keyFlag == True) {
			$this->config[$site][$mode][$serviceName] = $serval;
		}
		else {
			$this->config[$site][$mode][self::KEY][$serviceName] = $serval;
		}
		$this->save();
	}


	public function getSite() {
		//return $this->site;
		return $this->config['site'];
		//return $this->sessionData('site');
	}

	public function setSite($site) {
		if(in_array($site, $this->valid_sites)) {
			//$this->site = $site;
			$this->config['site'] = $site;
			$this->save();
		}
		else {
			throw new Macys_Base_Exception('Invalid SITE Please set Valid Site');
		}
	}

	/**
	 * Provides the current configuration
	 * of OAuth Details the Client can use
	 */
	public function getOAuthDetails() {
		return array ('client_id' => $this->config[$this->getSite()][self::APIPROXY]['oauth']['client_id'],
						'secret' => $this->config[$this->getSite()][self::APIPROXY]['oauth']['secret'],
						'mashery_uri' => $this->getApiUri(),
						'auth_uri' => $this->config[$this->getSite()]['oauth']['url'],
		);
	}

	public function getManualUserContext($isForm = FALSE) {
		if(isset($this->config[Macys_Constants::MACYS_USER_CONTEXT])) {
			if($isForm == TRUE) {
				return array ('usercontextforform' => $this->config[Macys_Constants::MACYS_USER_CONTEXT]);
			}
			else {
				return $this->config[Macys_Constants::MACYS_USER_CONTEXT];
			}
		}
		return false;
	}

	public function setManualUserContext($userContext=null) {
		if(isset($userContext['usercontextforform'])) {
			$context = $userContext['usercontextforform'];
			if($context == null || $context == "") {
				unset($this->config[Macys_Constants::MACYS_USER_CONTEXT]);
			}
			else {
				$this->config[Macys_Constants::MACYS_USER_CONTEXT] = $context;
			}
			$this->save();
			return $this;
		}
	}

	public function getProxy() {
		if($this->checkProxy()) {
			if($this->config['proxyserverworking'] == TRUE)
			return $this->config['proxy'];
			else
			return FALSE;
		}
		else {
			return FALSE;
		}
	}

	public function checkProxy(){
		if(isset($this->config['proxyserverchecked'])) {
			if($this->config['proxyserverchecked'] == FALSE) {
				if(isset($this->config['proxy'])) {
					$r = $this->ping($this->config['proxy']['host']);
					if($r) {
						$this->config['proxyserverworking'] = TRUE;
						//$this->save();
					}
				}
			}
			$this->config['proxyserverchecked'] = TRUE;
			$this->save();
			return $this->config['proxyserverchecked'];
		}
		$this->config['proxyserverchecked'] = FALSE;
		$this->config['proxyserverworking'] = FALSE;
		$this->save();
		return $this->checkProxy();
	}

	public function setProxy($proxy) {
		if(!isset($proxy['host']) || !isset($proxy['username']) || !isset($proxy['password'])) {
			throw new Macys_Base_Exception('Proxy Information not properly set');
		}
		$this->config['proxyserverchecked'] = FALSE;
		$this->config['proxyserverworking'] = FALSE;
		$this->config['proxy'] = $proxy;
		$this->save();
	}

	/**
	 * We want to make sure that we need to use the proxy configured
	 * If the configured proxy IP / host name does not work then we cannot use that proxy server conf
	 * @param string $host
	 */

	private function ping($host) {
		$ip = gethostbyname($host);
		$this->log->crit("Host Details by Host Name : " . $ip);
		if($host != $ip) {
			if(ip2long($ip) == -1 || ($ip == gethostbyaddr($ip) && preg_match("/.*\.[a-zA-Z]{2,3}$/",$host) == 0) ) {
				return false;
			}
			else {
				return true;
			}
		}
		else {
			return false;
		}

	}

	/**
	 * Saves this Class's info to Session
	 * Provides connectivity to Session class
	 * @param string $key
	 * @param Mixed $value
	 */
	private function sessionData($key, $value = null) {
		return $this->session->sessionData(self::SESSION_NAME, $key, $value);
	}



}